using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Batalha_Estelar
{
    public class BatalhaEstelar : Microsoft.Xna.Framework.Game
    {

        #region Fields
        
        public GameState State { get; set; }
        public GameConfig Config { get; set; }
        
        protected SpriteBatch SpriteBatch { get; set; }
        protected GraphicsDeviceManager Graphics { get; set; }
        protected EnemyController MyEnemyController { get; set; }
        protected PlayerShip PlayerShip { get; set; }
        protected GameOver GameOverScreen { get; set; }

        #endregion

        #region Construtor

        public BatalhaEstelar()
        {
            Config = GameConfig.GetDefault();
            Graphics = new GraphicsDeviceManager(this);
            State = new GameState();
            GameOverScreen = new GameOver(this);
            
            Graphics.PreferredBackBufferWidth = Config.FieldWidth;
            Graphics.PreferredBackBufferHeight = Config.FieldHeight;

            Content.RootDirectory = Config.RootDirectory;

            MyEnemyController = new EnemyController(this);
        }

        #endregion

        #region Game Methods

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            SpriteBatch = new SpriteBatch(GraphicsDevice);

            var factory = new ShipFactory(this);
            var position = Config.Player1_StartPosition;

            PlayerShip = factory.CreatePlayerShip("Player1", position);
        }

        protected override void UnloadContent()
        {
           
        }

        protected override void Update(GameTime gameTime)
        {
            DetectColisions(PlayerShip);
            State.RemoveAll((x) => x.CanDestroy());
            Controle(gameTime);

            if (State.IsGameOver())
            {
                State.Clear();
                State.Add(GameOverScreen);
            }
            else
            {
                MyEnemyController.criarInimigo(gameTime);
                MyEnemyController.MoveShips(gameTime);
            }

            State.GameObjects.ForEach((x) => x.Update(gameTime));

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Config.BackGroundColor);
            SpriteBatch.Begin();
            State.GameObjects.ForEach((x) => x.Draw(SpriteBatch));
            SpriteBatch.End();

            base.Draw(gameTime);

            //if (nave.getVida() <= 0)
            //{
            //    GraphicsDevice.Clear(Config.BackGroundColor);
            //    SpriteBatch.Begin();
            //    gameOver.Draw(SpriteBatch);
            //    SpriteBatch.End();

            //    base.Draw(gameTime);
            //}
            //else
            //{
            //    GraphicsDevice.Clear(config.BackGroundColor);

            //    SpriteBatch.Begin();
            //    nave.Draw(SpriteBatch);
            //    MyEnemyController.Draw(SpriteBatch);
            //    SpriteBatch.End();

            //    base.Draw(gameTime);
            //}
        }

        #endregion

        #region Helpers

        private void DetectColisions(PlayerShip playerShip)
        {
            var playerShipBounds = playerShip.GetBounds();
            
            var missiles = State.Query().OfType<Missel>();
            var enemies = this.State.Query().OfType<EnemyShip>();

            var playerMissiles = missiles.Where((x) => x.Ship == playerShip).ToList();

            foreach (var ship in enemies)
            {
                var shipBounds = ship.GetBounds();

                if (shipBounds.Intersects(playerShipBounds))
                {
                    ship.Colision = true;
                    playerShip.Colision = true;
                    playerShip.DecrementLife();
                }

                foreach (var missel in playerMissiles)
                {
                    var misselBounds = missel.GetBounds();

                    if (misselBounds.Intersects(shipBounds))
                    {
                        missel.Colision = true;
                        ship.Colision = true;
                    }
                }
            }

            var enemyMissiles = State.Query().OfType<Missel>().Where((x) => !(x.Ship is PlayerShip));

            foreach (var missel in enemyMissiles)
            {
                var misselBounds = missel.GetBounds();

                if (misselBounds.Intersects(playerShipBounds))
                {
                    missel.Colision = true;
                    playerShip.Colision = true;
                    playerShip.DecrementLife();
                }
            }

        }

        private void Controle(GameTime gameTime)
        {
            KeyboardState teclado = Keyboard.GetState();

            var v = new Vector2(0.0f, 0.0f);

            if (teclado.IsKeyDown(Keys.Escape))
            {
                Exit();
            }

            if (teclado.IsKeyDown(Keys.Right))  
            {
                v.X += 1.0f;
            }
            if (teclado.IsKeyDown(Keys.Left)) 
            {
                v.X -= 1.0f;
            }
            if (teclado.IsKeyDown(Keys.Down)) 
            {
                v.Y += 1.0f;
            }
            if (teclado.IsKeyDown(Keys.Up)) 
            {
                v.Y -= 1.0f;
            }

            PlayerShip.Direcao = v;

            if (teclado.IsKeyDown(Keys.A))
            {
                PlayerShip.Atirar(gameTime, PlayerShip.Posicao);
            }

            if (teclado.IsKeyDown(Keys.Enter) && State.IsGameOver())
            {
                PlayerShip.ResetLifes();
                State.Add(PlayerShip);
                var hud = new Hud(this, PlayerShip);
                State.Add(hud);
            }
        }

        #endregion

    }
}
